package com.xhdx.ati.adau.controller.service.flow;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricIdentityLink;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xhdx.ati.adau.entity.FlowEntity;
import com.xhdx.ati.adau.entity.TaskEntity;

@Service
public class ActiFlowService {
	private static final Log logger = LogFactory.getLog(ActiFlowService.class);
	
	private static String BPMN = "bpmn";
	@Autowired(required = false)
	ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
	@Autowired(required = false)
	private RuntimeService runtimeService;
	@Autowired(required = false)
	private TaskService taskService;
	@Autowired(required = false)
	RepositoryService repositoryService;
	
	@Autowired(required = false)
	private HistoryService historyService;

	/**
	 * 其实：taskService = processEngine.getTaskService(); runtimeService =
	 * processEngine.getRuntimeService(); repositoryService =
	 * processEngine.getRepositoryService();historyService = processEngine.getHistoryService();
	 */

	/**
	 * @Description: 部署工作流,发布自己定义的工作流一次性工作(插入到表中)，如果流程图有更新可以再次部署，其它就一次部署就行。例如：请假流程 对应表如下
	 *               act_re_deployment：流程定义部署表，记录流程部署信息。每次执行插入一条记录
	 *               act_re_procdef：流程定义表，记录流程定义信息。每次执行插入一条记录
	 *               act_ge_bytearray：资源表（bpmn文件和png文件）。每次执行插入二条记录，一个bpmn和png记录
	 * @return
	 */
	public Deployment deploy(FlowEntity flowEntity) {
		Deployment deployment = repositoryService.createDeployment()// 创建部署对象
				.addClasspathResource(BPMN + File.separator + flowEntity.getBpmn())
				.addClasspathResource(BPMN + File.separator + flowEntity.getPng()).name(flowEntity.getName()).deploy();
		return deployment;
	}

	/**
	 * 如果已启动流程报异常 .deleteDeployment(deploymentId); 使用部署id删除级联删除，删除已经启动的流程
	 */
	public void deleteProcessDefinition(String deploymentId) {
		repositoryService.deleteDeployment(deploymentId, true);
		logger.info("删除成功：" + deploymentId);
	}

	/**
	 * 
	 * 获取图片
	 * 
	 * 
	 * 
	 * @throws IOException
	 * 
	 */
	public void viewImage(String deploymentId)

	{
		//String deploymentId = "15001";
		String imageName = "";
		List<String> deploymentResourceNames = processEngine.getRepositoryService()
				.getDeploymentResourceNames(deploymentId);

		for (String name : deploymentResourceNames)
		{
			if (name.endsWith(".png"))
			{
				imageName = name;
				break;
			}
		}
		InputStream in = processEngine.getRepositoryService().getResourceAsStream(deploymentId, imageName);
		File file = new File("D:\\" + imageName);
	}

	/**
	 * @Description: 启动一个流程实例，往act_ru_task表中插入一条任务；
	 *               往act_ru_execution表中插入二条记录，一条开始节点，一条任务做到那个节点[REV_字段指定]
	 *               对应表如下： act_ru_execution(流程实例表), 管理流程进度 act_ru_task(任务表),
	 *               进行到哪一个流程的哪一个任务, 该由谁完成
	 * @param processDefinitionKey使用act_re_procdef流程定义的key启动流程实例 key对应bpmn文件的id属性值
	 */
	public String startProcess(String processDefinitionKey) {
		// String processDefinitionKey = "myProcess";
		// 创建流程变量
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("users", "xiaomingliang,lixiao");// 在启动时设置流程变量
		// 方式一：根据流程定义id启动流程实例
		// String processDefinitionId = "qjlc:6:904";
		// ProcessInstance processInstance =
		// runtimeService.startProcessInstanceById(processDefinitionId);

		// 方式二：根据流程定义Key启动流程实例 推荐!流程定义有多个版本时会选择最新版本
		ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
		return pi.getId() + ":" + pi.getDescription() + ":" + pi.getProcessInstanceId();
	}

	/**
	 * @Description: 办理任务/完成某任务, 办理后框架自动移动到下一任务
	 *               (即act_ru_task任务id值伴随更新，act_ru_execution任务REV_值伴随更新；
	 *               直到最后任务节点执行完毕，删除这条任务)
	 * @param taskId
	 *            来源act_ru_task 对应id值 对应表如下:
	 *            act_ru_execution(流程实例表)、act_ru_task(任务表)
	 */
	public void handleTask(String taskId) {
		// String taskId = "1304";
		taskService.complete(taskId);
	}
	/**
	 * 任务这块加入业务：
	 * 查询自己申请的任务
	 */
	public void applyQuery(String taskId, String applyName) {
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("申请人", applyName);// 在启动时设置流程变量
		taskService.complete(taskId, variables);
	}
	/**
	 * 任务这块加入业务：
	 * 部门经理查询自己的任务
	 * @param group="manageGroups"
	 */
	public List<TaskEntity> groupQueryTasks(String group) {
		List<Task> taskList = taskService.createTaskQuery().taskCandidateGroup(group)
                .list();
		
		//任务列表的展示
		List<TaskEntity> a = changeTasks(taskList);
        return a;
	}
	/**
	 * 任务这块加入业务：
	 * 总经理查询自己的任务
	 */
	public List<TaskEntity>  userQueryTasks(String user) {
//		Map<String, Object> variables = new HashMap<String, Object>();
//		variables.put("申请人", applyName);// 在启动时设置流程变量
		//目前这种此框架暂时不能使用
//		List<Task> taskList = taskService.createTaskQuery().taskCandidateUser(user)
//                .list();
		List<Task> taskList = taskService.createTaskQuery().taskAssignee(user)//任务负责人
      .list();
		
		//任务列表的展示
		List<TaskEntity> a = changeTasks(taskList);
        return a;
	}
	/**
	 * 任务这块加入业务：
	 * 查询表中所有任务
	 */
	public List<TaskEntity>  queryAllTasks() {
		List<Task> taskList = taskService.createTaskQuery()
                .list();
		
		//任务列表的展示
		List<TaskEntity> a = changeTasks(taskList);
        return a;
	}
	/**
	 * @Description: 查询流程定义 对应表：act_re_procdef
	 */
	public List<ProcessDefinition> query(String processDefinitionKey) {
		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
		// 查询条件过滤
		query.processDefinitionKey(processDefinitionKey);
		query.orderByProcessDefinitionVersion().asc();
		List<ProcessDefinition> list = query.listPage(0, 10);
		return list;
	}
	/**
     * 拾取任务 组任务分配给个人任务 指定任务的办理人字段，相当于领取任务
     */
    public void claim(String userId, String taskId) {
        //个人Id
        //String userId = "郭靖";
        //String taskId = "10404";
        //可以是组任务的成员 也可以是其他人
        taskService.claim(taskId, userId);
    }
    /**
     * 查询正在执行的某个任务办理人表
     */
    public List<String> findRunPersonTask(String taskId) {
    	List<String> listSinfo = null;
//        String taskId = "8701";
        List<IdentityLink> list = taskService
                        .getIdentityLinksForTask(taskId);
        if (list!=null&&list.size()>0) {
        	String e =null;
        	listSinfo = new ArrayList<>(list.size());
            for (IdentityLink identityLink : list) {
            	e = identityLink.getUserId()+" "
                        +identityLink.getProcessInstanceId()+" "
                        +identityLink.getType();
            	logger.info(e);
            	listSinfo.add(e);
            }
        }
        return listSinfo;
    }

    /**
     * 查询历史任务的办理人
     */
    public List<String> findHistoryPersonTask(String processInstanceId) {
    	List<String> listSinfo = null;
//        String processInstanceId = "8901";
        List<HistoricIdentityLink> list = historyService.getHistoricIdentityLinksForProcessInstance(processInstanceId);
        if (list!=null&&list.size()>0) {
        	String e =null;
        	listSinfo = new ArrayList<>(list.size());
            for (HistoricIdentityLink historicIdentityLink : list) {
            	e = historicIdentityLink.getTaskId()+" "
                        +historicIdentityLink.getType()+" "
                        +historicIdentityLink.getProcessInstanceId();
            	logger.info(e);
            	listSinfo.add(e);
            }
        }
        return listSinfo;
    }

	/**
	 * 任务转换
	 * @return
	 */
	private List<TaskEntity> changeTasks(List<Task> taskList){
		List<TaskEntity> taskEntityList = null;
		if(taskList!=null && taskList.size()>0){
			taskEntityList = new ArrayList<TaskEntity>(taskList.size());
			
			TaskEntity te = null;
			for(Task task :taskList){	            
	            logger.info("任务ID"+task.getId());
	            logger.info("任务名称"+task.getName());
	            logger.info("任务创建时间"+task.getCreateTime());
	            logger.info("任务的办理人"+task.getAssignee());
	            logger.info("流程实例id:"+task.getProcessInstanceId());
	            logger.info("执行对象id:"+task.getExecutionId());
	            logger.info("流程定义id:"+task.getProcessDefinitionId());
	            
	            te = new TaskEntity();
	            te.setProcessInstanceId(task.getProcessInstanceId());
	            te.setId(task.getId());
	            te.setAssignee(task.getAssignee());
	            te.setName(task.getName());
	            te.setCreateTime(task.getCreateTime());
	            te.setExecutionId(task.getExecutionId());
	            te.setProcessDefinitionId(task.getProcessDefinitionId());
	            
	            taskEntityList.add(te);
	        }
		}
		
		return taskEntityList;
	}
}
